package com.lab.network.util;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.NetworkInfo.State;
import android.net.TrafficStats;
import android.os.Build;
import android.os.SystemClock;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Pair;

import com.lab.logtrack.AppLog;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


public class NetworkUtil {
    public static final int CONNECT_NONE = 0x00;
    public static final int CONNECT_WIFI = 0x01;
    public static final int CONNECT_2G = 0x02;
    public static final int CONNECT_3G = 0x03;
    public static final int CONNECT_4G = 0x04;
    public static final int CONNECT_MOBILE = 0x05;
    //	public static final int CONNECT_WIMAX = 0x03;
    public static final int CONNECT_UNKNOWN = 0x06;
    public static final int CONNECT_ETHERNET = CONNECT_WIFI; //以太网处理逻辑同wifi
    public static final int CONNECT_FREE_MOBILE = 0x07; //免流量模式下的移动网络


    public static final int getConnectState(Context context) {
        if (context == null) {
            return CONNECT_NONE;
        }

        ConnectivityManager connectivityManager = (ConnectivityManager) context
                .getSystemService(Context.CONNECTIVITY_SERVICE);
        if (connectivityManager == null) {
            return CONNECT_NONE;
        }
        NetworkInfo activeNetInfo;
        try {
            activeNetInfo = connectivityManager.getActiveNetworkInfo();
        } catch (NullPointerException e) { //getActiveNetworkInfo实现可能会坑爹的npe
            return CONNECT_NONE;
        }
        if (activeNetInfo != null
                && activeNetInfo.getState() == State.CONNECTED) {
            int type = activeNetInfo.getType();
            if (type == ConnectivityManager.TYPE_WIFI) {
                return CONNECT_WIFI;
            } else if (type == ConnectivityManager.TYPE_WIMAX) {
                return CONNECT_MOBILE;
            } else if (type == ConnectivityManager.TYPE_MOBILE) {
                return CONNECT_MOBILE;
            } else if (type == ConnectivityManager.TYPE_ETHERNET) {
                return CONNECT_ETHERNET;
            }
            return CONNECT_UNKNOWN;
        } else {
            return CONNECT_NONE;
        }
    }

    public static int getNetworkTypeInt(Context context) {
        int type = 0;
        if (context == null) return type;
        ConnectivityManager connectivityManager = (ConnectivityManager) context
                .getSystemService(Context.CONNECTIVITY_SERVICE);
        if (connectivityManager == null) {
            return type;
        }
        NetworkInfo activeNetInfo = connectivityManager.getActiveNetworkInfo();
        if (activeNetInfo != null) {
            if (activeNetInfo.getType() == ConnectivityManager.TYPE_WIFI) {
                type = CONNECT_WIFI;
            } else if (activeNetInfo.getType() == ConnectivityManager.TYPE_MOBILE) {
                int ntype = activeNetInfo.getSubtype();
                if (ntype == TelephonyManager.NETWORK_TYPE_GPRS || ntype == TelephonyManager.NETWORK_TYPE_EDGE
                        || ntype == TelephonyManager.NETWORK_TYPE_CDMA) {
                    type = CONNECT_2G;
                } else if (ntype == TelephonyManager.NETWORK_TYPE_EVDO_A || ntype == TelephonyManager.NETWORK_TYPE_HSDPA
                        || ntype == TelephonyManager.NETWORK_TYPE_EVDO_0 || ntype == TelephonyManager.NETWORK_TYPE_EVDO_B
                        || ntype == TelephonyManager.NETWORK_TYPE_UMTS) {
                    type = CONNECT_3G;
                } else if (ntype == TelephonyManager.NETWORK_TYPE_LTE) {
                    type = CONNECT_4G;
                }
            } else {
                type = 0;
            }
        }
        return type;
    }

    public static String getNetworkTypeName(Context context) {
        String sType = "unknown";
        if (context == null) {
            return "unknown";
        }
        ConnectivityManager connectivityManager = (ConnectivityManager) context
                .getSystemService(Context.CONNECTIVITY_SERVICE);
        if (connectivityManager == null) {
            return "unknown";
        }
        NetworkInfo activeNetInfo = connectivityManager.getActiveNetworkInfo();
        if (activeNetInfo != null) {
            if (activeNetInfo.getType() == ConnectivityManager.TYPE_WIFI) {
                sType = "wifi";
            } else if (activeNetInfo.getType() == ConnectivityManager.TYPE_MOBILE) {
                int type = activeNetInfo.getSubtype();
                if (type == TelephonyManager.NETWORK_TYPE_GPRS || type == TelephonyManager.NETWORK_TYPE_EDGE
                        || type == TelephonyManager.NETWORK_TYPE_CDMA) {
                    sType = "2g";
                } else if (type == TelephonyManager.NETWORK_TYPE_EVDO_A || type == TelephonyManager.NETWORK_TYPE_HSDPA
                        || type == TelephonyManager.NETWORK_TYPE_EVDO_0 || type == TelephonyManager.NETWORK_TYPE_EVDO_B
                        || type == TelephonyManager.NETWORK_TYPE_UMTS) {
                    sType = "3g";
                } else if (type == TelephonyManager.NETWORK_TYPE_LTE) {
                    sType = "4g";
                }
            } else {
                sType = "unknown";
            }
        }
        return sType;
    }

    public static final boolean isConnectMobileNetwork(Context context) {
        ConnectivityManager connectivityManager = (ConnectivityManager) context
                .getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo activeNetInfo = connectivityManager.getActiveNetworkInfo();
        if (activeNetInfo != null && activeNetInfo.isConnected()) {
            if (activeNetInfo.getType() == ConnectivityManager.TYPE_WIMAX) {
                return true;
            }

            NetworkInfo mobileInfo = connectivityManager
                    .getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
            if (mobileInfo != null) {
                int subType = mobileInfo.getSubtype();
                AppLog.d("mobile subtype:" + subType);
                if (subType == TelephonyManager.NETWORK_TYPE_EVDO_0
                        || subType == TelephonyManager.NETWORK_TYPE_EVDO_A
                        || subType == TelephonyManager.NETWORK_TYPE_EVDO_B
                        || subType == TelephonyManager.NETWORK_TYPE_HSDPA
                        || subType == TelephonyManager.NETWORK_TYPE_HSPA
                        || subType == TelephonyManager.NETWORK_TYPE_HSUPA
                        || subType == TelephonyManager.NETWORK_TYPE_UMTS
                        || subType == TelephonyManager.NETWORK_TYPE_EDGE
                        || subType == TelephonyManager.NETWORK_TYPE_CDMA) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * {wifi,mobile}
     *
     * @param context
     * @return
     */
    public static Pair<long[], Long> getTrafficStatsBytes(Context context) {
        long[] stats = new long[2];
        SharedPreferences sp = context.getSharedPreferences(
                FILE_SHARE_PERFERENCES, Context.MODE_PRIVATE);
        stats[0] = sp.getLong(KEY_STAT_WIFI_BYTES, -1);
        stats[1] = sp.getLong(KEY_STAT_MOBILE_BYTES, -1);
        long cleanTime = sp.getLong(KEY_LAST_CLEAN, 0);
        return new Pair<long[], Long>(stats, cleanTime);
    }

    public static void cleanTrafficStats(Context context) {
        SharedPreferences sp = context.getSharedPreferences(
                FILE_SHARE_PERFERENCES, Context.MODE_PRIVATE);
        Editor editor = sp.edit();
        editor.putLong(KEY_LAST_CLEAN, System.currentTimeMillis());
        editor.putLong(KEY_STAT_MOBILE_BYTES, 0);
        editor.putLong(KEY_STAT_WIFI_BYTES, 0);
        editor.commit();
    }

    private static final String KEY_STAT_WIFI_BYTES = "key_stat_wifi_bytes";
    private static final String KEY_STAT_MOBILE_BYTES = "key_stat_mobile_bytes";
    private static final String FILE_SHARE_PERFERENCES = "LIBRARY";
    private static final String KEY_LAST_UID_RX_BYTES = "key_last_uid_rx_bytes";
    private static final String KEY_LAST_NETWORK_TYPE = "key_last_network_type";
    private static final String KEY_LAST_CLEAN = "key_last_clean";
    private static final String kEY_LAST_BOOT_TIME = "key_last_boot_time";

    /**
     * 某些系统上会把MediaPlayer使用的流量计算到系统进程上
     *
     * @param context
     */
    @SuppressLint("NewApi")
    public static void saveTrafficStats(Context context) {

        if (Build.VERSION.SDK_INT > 7) {
            int uid = context.getApplicationInfo().uid;
            ConnectivityManager connectivityManager = (ConnectivityManager) context
                    .getSystemService(Context.CONNECTIVITY_SERVICE);
            NetworkInfo info = connectivityManager.getActiveNetworkInfo();
            SharedPreferences sp = context.getSharedPreferences(
                    FILE_SHARE_PERFERENCES, Context.MODE_PRIVATE);
            long lastSavedBytes = sp.getLong(KEY_LAST_UID_RX_BYTES, 0);
            long bootTime = System.currentTimeMillis()
                    - SystemClock.uptimeMillis();
            long lastBootTime = sp.getLong(kEY_LAST_BOOT_TIME, bootTime);
            if (Math.abs(lastBootTime - bootTime) > 10000) {
                lastSavedBytes = 0;//reset last saved Bytes after rebooted
            }

            long wifiBytes = sp.getLong(KEY_STAT_WIFI_BYTES, 0);
            long mobileBytes = sp.getLong(KEY_STAT_MOBILE_BYTES, 0);

            int lastType = sp.getInt(KEY_LAST_NETWORK_TYPE, -1);
            long currentBytes = TrafficStats.getUidRxBytes(uid);// all interface
            long newBytes = currentBytes - lastSavedBytes;

            if (lastType == ConnectivityManager.TYPE_WIFI) {
                wifiBytes += newBytes;
            } else if (lastType == ConnectivityManager.TYPE_MOBILE
                    || lastType == ConnectivityManager.TYPE_WIMAX
                    || lastType == ConnectivityManager.TYPE_MOBILE_DUN
                    || lastType == ConnectivityManager.TYPE_MOBILE_HIPRI
                    || lastType == ConnectivityManager.TYPE_MOBILE_MMS
                    || lastType == ConnectivityManager.TYPE_MOBILE_SUPL) {
                mobileBytes += newBytes;
            }
            Editor editor = sp.edit();
            if (!sp.contains(KEY_LAST_CLEAN)) {
                editor.putLong(KEY_LAST_CLEAN, System.currentTimeMillis()
                        - SystemClock.uptimeMillis());
            }
            editor.putInt(KEY_LAST_NETWORK_TYPE,
                    info == null ? -1 : info.getType());
            editor.putLong(KEY_LAST_UID_RX_BYTES, currentBytes);
            editor.putLong(KEY_STAT_MOBILE_BYTES, mobileBytes);
            editor.putLong(KEY_STAT_WIFI_BYTES, wifiBytes);
            editor.commit();
        }
    }

    public static int getProxyType(Context context) {
        if (context == null) return 0;
        ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo infp = connectivityManager.getActiveNetworkInfo();
        if (infp != null) {
            int type = infp.getType();
            String sProxy = android.net.Proxy.getHost(context);
            if (TextUtils.isEmpty(sProxy)) {
                if (type == ConnectivityManager.TYPE_WIFI) {

                } else if (type == ConnectivityManager.TYPE_MOBILE) {
                    TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
                    String operatorCode = telephonyManager.getSimOperator();
                    if ("46000".equals(operatorCode) || "46002".equals(operatorCode) || "46007".equals(operatorCode)) {
                        return 2;
                    } else if ("46001".equals(operatorCode) || "46006".equals(operatorCode)) {
                        return 1;
                    } else if ("46003".equals(operatorCode) || "46005".equals(operatorCode)) {
                        return 3;
                    }
                    return 3;
                }
            } else {
                return 0;//没用代理
            }
        }
        return 3;
    }

    /**
     * 根据host获取ip
     *
     * @param host
     * @return
     */
    public static String getIP(String host) {
        InetAddress address = null;
        try {
            address = InetAddress.getByName(host);
            return address.getHostAddress().toString();
        } catch (UnknownHostException e) {
            AppLog.w(e.getMessage());
            return null;
        }
    }

    /**
     * 获取url host
     *
     * @param url
     * @return
     */
    public static String getHost(String url) {
        if (url == null || url.trim().equals("")) {
            return "";
        }
        String host = "";
        Pattern p = Pattern.compile("(?<=//|)((\\w)+\\.)+\\w+");
        Matcher matcher = p.matcher(url);
        if (matcher.find()) {
            host = matcher.group();
        }
        return host;
    }
}
